/*
 leetcode 290 单词规律
 给定一种规律 pattern 和一个字符串 s ，判断 s 是否遵循相同的规律。

这里的 遵循 指完全匹配，例如， pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。

 

示例1:

输入: pattern = "abba", s = "dog cat cat dog"
输出: true
示例 2:

输入:pattern = "abba", s = "dog cat cat fish"
输出: false
示例 3:

输入: pattern = "aaaa", s = "dog cat cat dog"
输出: false
 

提示:

1 <= pattern.length <= 300
pattern 只包含小写英文字母
1 <= s.length <= 3000
s 只包含小写英文字母和 ' '
s 不包含 任何前导或尾随对空格
s 中每个单词都被 单个空格 分隔
*/

#include <iostream>
#include <unordered_map>
#include <sstream>
using namespace std;

bool wordPattern(string pattern, string s) {
    unordered_map<char, string> charToWord; // 保存 pattern 中字符到单词的映射
    unordered_map<string, char> wordToChar; // 保存单词到 pattern 中字符的映射

    istringstream ss(s); // 将字符串 s 转换为输入流
    string word;
    int i = 0;

    //ss>>word 从字符串流中读取一个单词放到 word
    while (ss >> word) {
        if (i >= pattern.size()) return false; // 单词数量多于 pattern 字符数量
        char c = pattern[i]; //从 pattern 中取出当前索引 i 对应的字符，赋值给变量 c

        // 检查 pattern->word 的映射
        if (charToWord.count(c)) { // 如果当前 pattern 字符已经有映射
            if (charToWord[c] != word) return false; // 如果映射不一致，返回 false
        } else {
            charToWord[c] = word; //如果不存在映射，则将当前单词和字符添加到 wordToChar 中
        }

        // 检查 word->pattern 的映射，过程同理
        if (wordToChar.count(word)) {
            if (wordToChar[word] != c) return false;
        } else {
            wordToChar[word] = c;
        }

        i++;
    }

    return i == pattern.size(); // 确保没有多余的模式字符
}

int main() {
    string pattern = "abba";
    string s = "dog cat cat dog";

    if (wordPattern(pattern, s)) {
        cout << "True" << endl;
    } else {
        cout << "False" << endl;
    }

    return 0;
}

/*
示例 1
输入：
pattern = "abba"
s = "dog cat cat dog"

执行过程：

第一次迭代：
当前单词："dog"
当前字符：'a'
wordToChar.count("dog") = 0（单词未映射）
添加映射：wordToChar["dog"] = 'a'

第二次迭代：
当前单词："cat"
当前字符：'b'
wordToChar.count("cat") = 0（单词未映射）
添加映射：wordToChar["cat"] = 'b'

第三次迭代：
当前单词："cat"
当前字符：'b'
wordToChar.count("cat") = 1（单词已映射）
检查映射：wordToChar["cat"] == 'b'，映射一致，继续。

第四次迭代：
当前单词："dog"
当前字符：'a'
wordToChar.count("dog") = 1（单词已映射）
检查映射：wordToChar["dog"] == 'a'，映射一致，继续。

结果： 映射通过，返回 true。


示例 2
输入：
pattern = "abba"
s = "dog cat cat fish"

步骤 1：初始化
charToWord = {}
wordToChar = {}
istringstream 分割 s 为单词流 ["dog", "cat", "cat", "fish"]。
i = 0

步骤 2：遍历模式和单词
第 1 次迭代
当前模式字符：'a'
当前单词："dog"
建立映射：
'a' -> "dog"
"dog" -> 'a'

第 2 次迭代
当前模式字符：'b'
当前单词："cat"
建立映射：
'b' -> "cat"
"cat" -> 'b'

第 3 次迭代
当前模式字符：'b'
当前单词："cat"
检查映射：
'b' 映射为 "cat"，一致。
"cat" 映射为 'b'，一致。

第 4 次迭代
当前模式字符：'a'
当前单词："fish"
检查映射：
'a' 映射为 "dog"，但当前单词是 "fish" → 不一致。

步骤 3：返回结果
映射不一致，返回 false。
*/